﻿<template>
  <div class="app-container">
    <div class="filter-title" style="text-align: right;">
      <el-form label-position="right" label-width="80px">
        <el-button
          v-if="permission.add"
          style="margin-left: 10px;"
          class="filter-item"
          type="primary"
          icon="el-icon-edit"
          @click="handleCreate"
          >{{ $t("table.add") }}</el-button
        >
      </el-form>
    </div>
    <el-table
      :data="tableListData"
      row-key="id"
      :row-style="toggleDisplayTr"
      border
      stripe
      class="init_table"
    >
      <el-table-column
        fixed="left"
        align="center"
        width="55"
        type="index"
        label="序号"
      ></el-table-column>
      <el-table-column
        :label="$t('goods.categoryName')"
        min-width="200"
        show-overflow-tooltip
        align="left"
      >
        <template slot-scope="scope">
          <p
            :style="
              `margin-left: ${scope.row.__level *
                20}px;margin-top:0;margin-bottom:0`
            "
          >
            <i
              class="permission_toggleFold"
              :class="toggleFoldingClass(scope.row)"
              @click="toggleFoldingStatus(scope.row)"
            ></i>
            {{ scope.row.name }}
          </p>
        </template>
      </el-table-column>
      <el-table-column
        align="center"
        show-overflow-tooltip
        :label="$t('goods.categoryPicture')"
      >
        <template slot-scope="scope">
          <img
            v-if="scope.row.picture"
            :src="scope.row.picture"
            width="150px"
            height="auto"
          />
        </template>
      </el-table-column>
      <el-table-column
        align="center"
        show-overflow-tooltip
        :label="$t('goods.description')"
      >
        <template slot-scope="scope">
          <span>{{ scope.row.description }}</span>
        </template>
      </el-table-column>
      <el-table-column
        align="center"
        show-overflow-tooltip
        :label="$t('public.createTime')"
      >
        <template slot-scope="scope">
          <span>{{ scope.row.create_time }}</span>
        </template>
      </el-table-column>
    </el-table>

    <!-- 编辑 -->
    <el-dialog :title="textMap[dialogStatus]" :visible.sync="dialogFormVisible">
      <el-form
        ref="dataForm"
        :rules="rules"
        :model="temp"
        label-position="right"
        label-width="35%"
        style="width: 400px margin-left:120px"
        size="small"
      >
        <el-form-item :label="$t('goods.categoryName')" prop="name">
          <el-input v-model="temp.name"></el-input>
        </el-form-item>
        <el-form-item :label="$t('goods.pid')" prop="pidName">
          <el-input v-model="pidName" disabled></el-input>
          <el-button type="primary" @click="chooseMenu">选择菜单</el-button>
        </el-form-item>
        <el-form-item :label="$t('goods.picture')" prop="picture">
          <div class="updateImage">
            <li
              v-if="picture"
              tabindex="0"
              class="el-upload-list__item is-success"
              style="width:150px;display:block"
            >
              <img
                :src="picture"
                alt
                class="el-upload-list__item-thumbnail"
                style="width:100%;height:auto"
              />
              <label class="el-upload-list__item-status-label">
                <i class="el-icon-upload-success el-icon-check"></i>
              </label>
              <i class="el-icon-close" @click="changPicture('picture')"></i>
              <i class="el-icon-close-tip"></i>
            </li>
            <div v-else>
              <button>
                点击上传
                <input
                  ref="file"
                  type="file"
                  class="uploadImagesInput"
                  @change="submitUpload('picture', 'upLoading')"
                />
              </button>
              只能上传jpg/png文件，且不超过500kb
            </div>
          </div>
        </el-form-item>
        <el-form-item :label="$t('goods.description')" prop="description">
          <el-input v-model="temp.description" type="textarea"></el-input>
        </el-form-item>
      </el-form>
      <div slot="footer" class="dialog-footer">
        <el-button @click="dialogFormVisible = false">{{
          $t("table.cancel")
        }}</el-button>
        <el-button
          v-if="dialogStatus == 'create'"
          type="primary"
          :disabled="!createDisabled"
          @click="createData"
          >{{ $t("table.confirm") }}</el-button
        >
      </div>
    </el-dialog>
    <!-- 选择菜单 -->
    <el-dialog title="父菜单" :visible.sync="dialogMenuRead">
      <el-tree
        :props="defaultProps"
        :data="menuList"
        @node-click="handleNodeClick"
      ></el-tree>
    </el-dialog>
  </div>
</template>

<script>
// import waves from "@/directive/waves"; // 水波纹指令
import Vue from "vue";

export default {
  data() {
    const pidName = (rule, value, callback) => {
      if (this.pidName) {
        callback();
      } else {
        callback(new Error("请选择上级菜单！"));
      }
    };
    const name = (rule, value, callback) => {
      if (value) {
        if (value.length > 10) {
          callback(new Error("名称长度不得超过10位！"));
        } else {
          callback();
        }
      } else {
        callback(new Error("请填写菜单名称！"));
      }
    };
    const description = (rule, value, callback) => {
      if (value) {
        if (value.length > 150) {
          callback(new Error("商品详情不得超过150位！"));
        } else {
          callback();
        }
      } else {
        callback(new Error("请填写商品详情！"));
      }
    };
    return {
      menuList: [],
      defaultProps: {
        children: "children",
        label: "name"
      },
      tableListData: [], // tableListData 展示数据的data
      foldList: [], // 该数组中的值 都会在列表中进行隐藏  死亡名单
      dialogStatus: "",
      createDisabled: true,
      textMap: {
        update: "更新",
        create: "添加",
        review: "审核",
        read: "查看"
      },
      temp: {
        id: undefined,
        name: "",
        pid: 0,
        level: 1,
        description: ""
      },
      pid_name: "",
      picture: "",
      rules: {
        name: [{ required: true, trigger: "blur", validator: name }],
        pidName: [{ required: true, trigger: "change", validator: pidName }],
        description: [
          { required: true, trigger: "change", validator: description }
        ]
      },
      permission: {
        add: false
      },
      dialogFormVisible: false,
      dialogFormRead: false,
      dialogMenuRead: false
    };
  },
  computed: {
    /** *******************************
     ** Fn: foldAllList
     ** Intro: 记录属性结构的首层节点
     ** Author: zyx
     ******************************* **/
    foldAllList() {
      return this.tableListData.map(x => x.__identity);
    },
    pidName() {
      return this.pid_name;
    }
  },
  created() {
    if (this.$store.state.permission.jurisdiction === "*") {
      this.permission.add = true;
    } else {
      const jurisdiction = this.$store.state.permission.jurisdiction.split(",");
      jurisdiction.forEach(element => {
        const id = parseInt(element);
        if (id === 199) {
          this.permission.add = true;
        }
      });
    }
    this.getData();
  },
  methods: {
    /** *******************************
     ** Fn: toggleFoldingStatus
     ** Intro: 切换展开 还是折叠
     ** @params: params 当前点击行的数据
     ** Author: zyx
     ******************************* **/
    toggleFoldingStatus(params) {
      this.foldList.includes(params.__identity)
        ? this.foldList.splice(this.foldList.indexOf(params.__identity), 1)
        : this.foldList.push(params.__identity);
    },
    /** *******************************
     ** Fn: toggleDisplayTr
     ** Intro: 该方法会对每一行数据都做判断 如果foldList 列表中的元素 也存在与当前行的 __family列表中  则该行不展示
     ** @params:
     ** Author: zyx
     ******************************* **/
    toggleDisplayTr({ row, index }) {
      for (let i = 0; i < this.foldList.length; i++) {
        const item = this.foldList[i];
        // 如果foldList中元素存在于 row.__family中，则该行隐藏。  如果该行的自身标识等于隐藏元素，则代表该元素就是折叠点
        if (row.__family.includes(item) && row.__identity !== item) {
          return "display:none;";
        }
      }
      return "";
    },
    /** *******************************
     ** Fn: toggleFoldingClass
     ** Intro: 如果子集长度为0，则不返回字体图标。
     ** Intro: 如果子集长度为不为0，根据foldList是否存在当前节点的标识返回相应的折叠或展开图标
     ** Intro: 关于class说明：permission_placeholder返回一个占位符，具体查看class
     ** @params: params 当前行的数据对象
     ** Author: zyx
     ******************************* **/
    toggleFoldingClass(params) {
      return params.childrens
        ? this.foldList.indexOf(params.__identity) === -1
          ? "iconfont icon-minus-square-o"
          : "iconfont icon-plussquareo"
        : "permission_placeholder";
    },
    /** *******************************
     ** Fn: formatConversion
     ** Intro: 将树形接口数据扁平化
     ** @params: parent 为当前累计的数组  也是最后返回的数组
     ** @params: children 为当前节点仍需继续扁平子节点的数据
     ** @params: index 默认等于0， 用于在递归中进行累计叠加 用于层级标识
     ** @params: family 装有当前包含元素自身的所有父级 身份标识
     ** @params: elderIdentity 父级的  唯一身份标识
     ** Author: zyx
     ******************************* **/
    formatConversion(
      parent,
      childrens,
      index = 0,
      family = [],
      elderIdentity = "x"
    ) {
      // children如果长度等于0，则代表已经到了最低层
      // let page = (this.startPage - 1) * 10
      if (childrens) {
        if (childrens.length > 0) {
          childrens.map((x, i) => {
            // 设置 __level 标志位 用于展示区分层级
            Vue.set(x, "__level", index);
            // 设置 __family 为家族关系 为所有父级，包含本身在内
            Vue.set(x, "__family", [...family, elderIdentity + "_" + i]);
            // 本身的唯一标识  可以理解为个人的身份证咯 一定唯一。
            Vue.set(x, "__identity", elderIdentity + "_" + i);
            parent.push(x);
            // 如果仍有子集，则进行递归
            if (x.childrens) {
              if (x.childrens.length > 0) {
                this.formatConversion(
                  parent,
                  x.childrens,
                  index + 1,
                  [...family, elderIdentity + "_" + i],
                  elderIdentity + "_" + i
                );
              }
            }
          });
        }
      }
      return parent;
    },
    getData() {
      const authRuleIndexPath = {
        company: "STQ",
        api: "pc_GoodsCategory_index",
        version: "1.0",
        data: {
          returnType: "getlist"
        }
      };
      this.socketApi.sendSock(JSON.stringify(authRuleIndexPath), res => {
        if (res) {
          this.socketData(res);
        }
      });
    },
    resetTemp() {
      this.temp = {
        id: undefined,
        name: "",
        pid: 0,
        level: 1,
        description: ""
      };
      this.pid_name = "";
      this.picture = "";
    },
    handleRefresh() {
      this.getData();
    },
    handleCreate() {
      this.resetTemp();
      this.dialogStatus = "create";
      this.dialogFormVisible = true;
      this.$nextTick(() => {
        this.$refs["dataForm"].clearValidate();
      });
    },
    createData() {
      // 添加菜单
      this.$refs["dataForm"].validate(valid => {
        if (valid) {
          if (this.createDisabled) {
            this.createDisabled = false;

            const data = {
              name: this.temp.name,
              pid: this.temp.pid,
              level: this.temp.level,
              description: this.temp.description,
              picture: this.picture
            };
            const goodsCategoryAddPath = {
              company: "STQ",
              api: "pc_GoodsCategory_add",
              version: "1.0",
              data: data
            };
            console.log(
              "JSON.stringify(goodsCategoryAddPath)",
              JSON.stringify(goodsCategoryAddPath)
            );
            this.socketApi.sendSock(
              JSON.stringify(goodsCategoryAddPath),
              res => {
                if (res) {
                  this.socketData(res);
                }
                setTimeout(() => {
                  this.createDisabled = true;
                }, 1000);
              }
            );
          }
        }
      });
    },
    socketData(res) {
      if (res !== '{"type":"ping"}') {
        const resj = JSON.parse(res);
        if (resj.code === -1) {
          this.$message.error(resj.message);
        } else {
          if (
            resj.api === "pc_GoodsCategory_index" &&
            resj.type === "getlist"
          ) {
            const data = JSON.parse(
              JSON.stringify(resj.data).replace(/children/g, "childrens")
            );
            this.tableListData = this.formatConversion([], data);
          } else if (
            resj.api === "pc_GoodsCategory_index" &&
            resj.type === "getMenu"
          ) {
            const menu = [
              {
                id: 0,
                name: "根目录",
                level: 0,
                children: []
              }
            ];
            if (resj.data) {
              menu[0].children = resj.data;
            }
            this.menuList = menu;
          } else if (resj.api === "pc_GoodsCategory_add") {
            this.dialogFormVisible = false;
            this.getData();
            this.$notify({
              title: "成功",
              message: "添加成功",
              type: "success",
              duration: 2000
            });
          }
        }
      }
    },
    submitUpload(name, loading) {
      this.upLoading = true;
      const video = new FormData();
      video.append("video", this.$refs.file.files[0]);
      const index = this.$refs.file.files[0].name.lastIndexOf(".");
      const suffix = this.$refs.file.files[0].name
        .substr(index + 1)
        .toLowerCase();
      const imageFile = ["jpg", "jpeg", "png"];
      if (imageFile.indexOf(suffix) !== -1) {
        if (this.$refs.file.files[0].size <= 500 * 1024) {
          this.updateFile(video, result => {
            if (result.data.code === 0) {
              this.$message.error(result.data.message);
            } else {
              this[name] = result.data.data.video_url;
            }
            this[loading] = false;
          });
        } else {
          this.$message.error("图片大小不得超过500kb");
          this[loading] = false;
          return false;
        }
      } else {
        this.$message.error("只能上传jpg/png文件");
        this[loading] = false;
        return false;
      }
    },
    changPicture(name) {
      this.$confirm("是否删除该视频源, 是否继续?", "提示", {
        confirmButtonText: "确定",
        cancelButtonText: "取消",
        type: "warning"
      })
        .then(() => {
          const index = this.picture.lastIndexOf("/");
          const str = this.picture.substring(index + 1, this.picture.length);
          const video_name = { video_name: str };
          this.deleteFile(video_name, result => {
            if (result.data.code === 0) {
              this.$message.error(result.data.message);
            } else {
              this[name] = "";
            }
          });
        })
        .catch(() => {
          this.$message({
            type: "info",
            message: "已取消删除"
          });
        });
    },
    chooseMenu() {
      this.dialogMenuRead = true;
      const authRuleIndexPath = {
        company: "STQ",
        api: "pc_GoodsCategory_index",
        version: "1.0",
        data: {
          returnType: "getMenu"
        }
      };
      this.socketApi.sendSock(JSON.stringify(authRuleIndexPath), res => {
        if (res) {
          this.socketData(res);
        }
      });
    },
    handleNodeClick(data) {
      this.temp.pid = data.id;
      this.pid_name = data.name;
      this.temp.level = parseInt(data.level) + 1;
      this.dialogMenuRead = false;
    }
  }
};
</script>

<style scoped>
.permission_toggleFold {
  width: 20px;
  height: 20px;
  text-align: center;
  line-height: 20px;
  display: inline-block;
  position: relative;
}
.permission_toggleFold.iconfont.icon-minus-square-o:after {
  content: "-";
  color: #9e9e9e;
  font-size: 20px;
}
.permission_toggleFold.iconfont.icon-plussquareo:after {
  content: "+";
  color: #9e9e9e;
  font-size: 20px;
}
</style>
